from pprint import pformat

from formencode.validators import Int

from clutch.globals import C, G
from clutch.controllers import Controller, SecureResource, RestMethod, redirect
from clutch.decorators import expose, validate, require
from clutch.exceptions import ContinueTraversal, HTTPGone
from clutch import api
from clutch.topes import *

from testapp import model as m
from testapp import commands as c

def not_anonymous():
    return C.request.environ.get('REMOTE_USER') is not None

def user_is(uname):
    def inner():
        return C.request.environ.get('REMOTE_USER') == uname
    return inner

class TestController(Controller):

    def __init__(self):
        self.controller = TestControllers()
        self.view = TestViews()
        self.model = TestModels()
        self.topes = TestTopes()

class TestModels(Controller):

    @expose()
    def create_schema(self):
        m.metadata.drop_all()
        m.metadata.create_all()
        api.call('id://create_schema')
        return 'Schema Created'

    @expose('json')
    def test_query_users(self):
        users = api.call('id://user/')
        return dict(users=users)

    @expose('json')
    def test_create_user(self):
        user = api.call('id://user/create',
                        email_address=u'rick446@usa.net')
        return dict(user=user)

    @expose('json')
    def test_error_id(self):
        user = api.call('id://user/create',
                        email_address=u'foo@bar')
        raise HTTPGone()

    class data(RestMethod):

        @expose('json')
        def get(self):
            return dict(items=m.ATest.query.all())

        @expose('json')
        def post(self):
            at = m.ATest()
            return dict(item=at)

        @expose('json')
        def put(self, id=None, value=None):
            at = m.ATest.query.get(id)
            at.value = value
            return dict(item=at)

        @expose('json')
        def delete(self, id=None):
            at = m.ATest.query.get(id)
            m.session.delete(at)
            return dict()

class TestViews(Controller):

    @expose('json')
    @expose('test/test1.html')
    @expose('jinja:test/test1.html', content_type='text/plain')
    def test1(self):
        return dict(a=5)

    @expose('safe_jinja:test/test2.html')
    def test2(self):
        return dict(func=lambda:None)
        

class TestControllers(Controller):

    def __init__(self):
        self.dfl_invalid = DefaultInvalidHandler()
        self.no_invalid = self.dfl_invalid.no_invalid = NoInvalidHandler()
        self.secure = SecureTest()
        self.secure.inner = self

    @expose()
    def index(self):
        'Index test'
        return 'Test Index'

    @expose()
    def test1(self):
        'Simple Test'
        return 'Test1'

    @expose()
    def test2a(self):
        'Redirect test (part 1)'
        redirect('/tests/controller/test2b')

    @expose()
    def test2b(self):
        'Redirect test (part 2)'
        return 'Test2'

    @expose()
    def test3a(self):
        'ContinueTraversal test (part 1)'
        raise ContinueTraversal(self, ['test3b'])

    @expose()
    def test3b(self):
        'ContinueTraversal test (part 2)'
        return 'Test3'

    def test4(self):
        'Test unexposed'
        assert False, 'This should never be called'

    class test5(RestMethod):

        @expose()
        def get(self):
            return 'Test5 get'

        @expose()
        def put(self):
            return 'Test5 put'

        def post(self):
            assert False, 'This should return bad method'

    @expose()
    def test6(self, **kw):
        return pformat(kw)

    @expose()
    def test7b(self, **kw):
        return pformat(kw)

    @expose()
    @validate(a=Int(),
              error_handler=test7b)
    def test7(self, **kw):
        return pformat(kw)

    @expose()
    @require(not_anonymous)
    def test8(self):
        return 'Test8'

    @expose()
    @require(user_is('rick'))
    def test9(self):
        return 'Test9'

class NoInvalidHandler(Controller):

    def _on_invalid(self, *args, **kwargs):
        exc_info = C.exc_info
        raise exc_info[0], exc_info[1], exc_info[2]

    @expose()
    @validate(a=Int())
    def index(self, **kw):
        return 'DefaultInvalid Index'

class DefaultInvalidHandler(Controller):

    def _on_invalid(self, *args, **kwargs):
        return pformat(dict(args=args, kwargs=kwargs, exc_info=C.exc_info))

    @expose()
    @validate(a=Int())
    def index(self, **kw):
        return 'DefaultInvalid Index'

class SecureTest(SecureResource):
    _require = [not_anonymous]

    @expose()
    def index(self):
        return 'SecureTest'

class TestTopes(Controller):
    s1 = ContentPane('cp1', label='Section 1', fields=[
        TextField('foo'),
        TextField('bar', label='Place to drink', help='My kind of place'),
        SSN('ssn', label='SSN'),
        LongText('long'),
        ResizingLongText('resizinglong'),
        ])
    s2 = ContentPane('cp2', label='Section 2', fields=[
        Date('date'),
        Time('time'),
        Currency('dollars', help='Give me all your money'),
        RichText('rich')
        ])

    sf = SimpleForm('myform', fields=[
        TabContainer('tabarea', attrs=dict(style='height:600px'), fields=[s1, s2])
        ],
                    )

    @expose('test/topes.html')
    @validate(sf.validator)
    def index(self, **kw):
        C.topes.test = self.sf
        print pformat(kw)
        return dict(value=kw)
